<!--
 * @Description: 列表信息节点组件
 * @Author: Auto
 * @Date: 2025-01-27
-->
<template>
  <div 
    class="table-node" 
    :class="nodeClass"
    :style="nodeStyle"
    @mousedown="handleNodeMouseDown"
    @dblclick="handleNodeDoubleClick"
  >
    <Handle id="top" type="target" position="top" />
    <Handle id="bottom" type="source" position="bottom" />
    <Handle id="left" type="target" position="left" />
    <Handle id="right" type="source" position="right" />
    
    <!-- 删除按钮 -->
    <div class="delete-btn" @click.stop="handleDelete" title="删除节点">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M11 3.5L3 11.5M3 3.5L11 11.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </div>
    
    <!-- 调整大小拖拽点 -->
    <div 
      class="resize-handle" 
      @mousedown.stop="handleResizeStart"
      title="拖拽调整大小"
    ></div>
    
    <!-- 进度条模式 -->
    <div v-if="progress < 100" class="progress-container">
      <div class="progress-bar-wrapper">
        <div class="progress-bar" :style="{ width: `${progress}%` }"></div>
      </div>
      <div class="progress-text">{{ Math.round(progress) }}%</div>
    </div>
    
    <!-- 节点内容模式 -->
    <template v-else>
      <div class="table-content" :data-node-id="nodeId">
        <!-- 标题 -->
        <div v-if="title" class="table-title">{{ title }}</div>
        <!-- 搜索模块 -->
        <DynamicSearch
          v-if="searchFields && searchFields.length > 0"
          :search-fields="searchFields"
          @search="handleSearch"
          @reset="handleReset"
        />
        <!-- 空状态 -->
        <div v-if="!filteredData || filteredData.length === 0" class="empty-container">
          <a-empty description="暂无数据" />
        </div>
        <!-- 有数据时显示 -->
        <template v-else>
          <a-table
            :data-source="tableData"
            :columns="tableColumns"
            size="small"
            :pagination="false"
            :scroll="{ y: tableHeight }"
            bordered
          />
          <a-pagination
            v-model:current="currentPage"
            v-model:page-size="pageSize"
            :total="total"
            :page-size-options="['5', '10', '20', '50']"
            show-size-changer
            show-quick-jumper
            :show-total="(total) => `共 ${total} 条`"
            size="small"
            class="pagination"
            @change="handlePageChange"
            @show-size-change="handleSizeChange"
          />
        </template>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onUnmounted, h, watch } from 'vue'
import { Handle } from '@vue-flow/core'
import DynamicSearch, { type SearchField } from './DynamicSearch.vue'
import dayjs from 'dayjs'

interface Props {
  title?: string // 标题
  columns?: Array<{ prop: string; label: string; width?: number; minWidth?: number }> // 表格列配置
  data?: any[] // 表格数据
  progress?: number // 进度 0-100
  nodeId?: string
  width?: number
  height?: number
  searchFields?: SearchField[] // 搜索字段配置
  selected?: boolean // 是否选中
}

const props = withDefaults(defineProps<Props>(), {
  title: '',
  columns: () => [
    { prop: 'name', label: '姓名', width: 100 },
    { prop: 'age', label: '年龄', width: 80 },
    { prop: 'address', label: '地址', minWidth: 150 }
  ],
  data: () => [],
  progress: 100,
  nodeId: '',
  width: undefined,
  height: undefined,
  searchFields: () => [],
  selected: false
})

const emit = defineEmits<{
  delete: [nodeId: string]
  resize: [nodeId: string, width: number, height: number]
  createPersonNode: [idNumber: string]
}>()

const nodeClass = computed(() => ({
  'node-table': true,
  'node-selected': props.selected
}))

const nodeStyle = computed(() => {
  const style: Record<string, string> = {}
  if (props.width !== undefined) {
    style.width = `${props.width}px`
  }
  if (props.height !== undefined) {
    style.height = `${props.height}px`
  }
  return style
})

// 搜索相关
const searchValues = ref<Record<string, any>>({})

// 过滤后的数据
const filteredData = computed(() => {
  if (!props.data || props.data.length === 0) return []
  if (!searchValues.value || Object.keys(searchValues.value).length === 0) return props.data
  
  // 分离时间范围字段和普通字段
  const timeRangeFields: Record<string, { start?: string; end?: string }> = {}
  const normalFields: Record<string, any> = {}
  
  Object.keys(searchValues.value).forEach(key => {
    const value = searchValues.value[key]
    if (value === null || value === undefined || value === '') {
      return
    }
    
    if (key.endsWith('Start')) {
      const fieldKey = key.replace(/Start$/, '')
      if (!timeRangeFields[fieldKey]) {
        timeRangeFields[fieldKey] = {}
      }
      timeRangeFields[fieldKey].start = value
    } else if (key.endsWith('End')) {
      const fieldKey = key.replace(/End$/, '')
      if (!timeRangeFields[fieldKey]) {
        timeRangeFields[fieldKey] = {}
      }
      timeRangeFields[fieldKey].end = value
    } else {
      normalFields[key] = value
    }
  })
  
  return props.data.filter(item => {
    // 检查时间范围字段
    for (const fieldKey in timeRangeFields) {
      const range = timeRangeFields[fieldKey]
      const fieldValue = item[fieldKey]
      if (!fieldValue) {
        if (range.start || range.end) return false
        continue
      }
      
      const itemDate = dayjs(fieldValue)
      
      if (range.start) {
        const startDate = dayjs(range.start)
        if (itemDate.isBefore(startDate, 'day')) return false
      }
      
      if (range.end) {
        const endDate = dayjs(range.end)
        if (itemDate.isAfter(endDate, 'day')) return false
      }
    }
    
    // 检查普通字段
    for (const key in normalFields) {
      const searchValue = normalFields[key]
      const itemValue = String(item[key] || '').toLowerCase()
      const searchStr = String(searchValue).toLowerCase()
      if (!itemValue.includes(searchStr)) {
        return false
      }
    }
    
    return true
  })
})

// 分页相关
const currentPage = ref(1)
const pageSize = ref(5)
const total = computed(() => filteredData.value.length)

// 监听搜索值变化，重置到第一页
watch(() => searchValues.value, () => {
  currentPage.value = 1
}, { deep: true })

// 计算表格高度
const tableHeight = computed(() => {
  const baseHeight = props.height || 300
  const titleHeight = props.title ? 40 : 0 // 如果有标题，减去标题高度
  const searchHeight = (props.searchFields && props.searchFields.length > 0) ? 50 : 0 // 搜索模块高度
  return baseHeight - 60 - titleHeight - searchHeight // 减去分页器高度、标题高度和搜索模块高度
})

// 身份证号码正则表达式（18位或15位）
// 18位：前17位数字 + 最后一位数字或X/x
// 15位：15位数字
// 注意：先匹配18位，再匹配15位，避免18位被15位模式截断
const idCardRegex = /(\d{17}[\dXx]|\d{15})/g

// SVG图标组件
const HandIcon = () => {
  return h('svg', {
    t: '1763026344096',
    class: 'icon',
    viewBox: '0 0 1024 1024',
    version: '1.1',
    xmlns: 'http://www.w3.org/2000/svg',
    pId: '1615',
    width: '14',
    height: '14',
    style: 'display: inline-block; vertical-align: middle; margin-right: 4px;'
  }, [
    h('path', {
      d: 'M864.65 336.975v-0.079c56.91 0 98.58 45.804 98.58 102.321v204.485c0 193.26-26.94 349.932-317.283 349.932-127.055 0-187.156-25.363-239.616-68.135a103.778 103.778 0 0 1-19.377-14.966L99.249 624.64c-48.994-49.034-26.584-117.957 7.759-152.222 34.265-34.343 105.433-39.975 145.723 0l62.425 62.307V137.689a102.676 102.676 0 0 1 103.03-102.243c56.91 0 99.643 45.726 99.643 102.243v103.817a102.4 102.4 0 0 1 48.6-12.209c45.293 0 80.463 29.066 94.287 69.317 15.754-9.728 34.856-15.517 54.863-15.517 45.292 0 80.384 29.065 94.208 69.395a95.31 95.31 0 0 1 52.145-15.517h2.757z m44.19 306.727v0.158h0.236V445.755c0-50.333-47.301-48.364-47.301-48.364-26.94 0-46.986 21.661-46.986 48.364v106.417h-0.551a31.114 31.114 0 0 1 0.55 5.435 26.466 26.466 0 0 1-26.544 26.86 27.018 27.018 0 0 1-26.546-32.295h-0.55v-156.12c0-45.332-48.76-48.404-48.76-48.404-26.938 0-46.08 21.7-46.08 48.404v123.943h-0.63a26.978 26.978 0 0 1-26.505 32.295 27.018 27.018 0 0 1-26.545-32.295h-0.552V342.37c0-49.112-47.773-48.443-47.773-48.443-26.94 0-46.474 21.662-46.474 48.443v134.538h-0.512a26.978 26.978 0 0 1-26.624 32.296 27.018 27.018 0 0 1-26.545-32.296h-0.512v-328.35c0-26.702-18.432-48.442-45.371-48.442-27.018 0-48.837 21.74-48.837 48.443v516.214c-49.231-48.837-98.383-97.753-147.535-146.629-19.062-18.905-55.257-18.196-74.949 1.575-19.653 19.693-25.758 50.452-1.694 74.595l272.306 270.533c50.53 50.176 117.248 74.91 228.234 74.91 262.262 0 263.05-132.53 263.05-296.055z',
      pId: '1616',
      fill: '#1890ff'
    })
  ])
}

// 检测文本中是否包含身份证号码
const hasIdCard = (text: string): boolean => {
  if (!text) return false
  return idCardRegex.test(String(text))
}

// 提取身份证号码
const extractIdCard = (text: string): string | null => {
  if (!text) return null
  const match = String(text).match(idCardRegex)
  return match ? match[0] : null
}

// 渲染带身份证号码的单元格内容
const renderCellWithIdCard = (text: string, record: any, column: any) => {
  const textStr = String(text || '')
  const idCard = extractIdCard(textStr)
  
  if (idCard) {
    // 分割文本，将身份证号码替换为可拖拽元素
    const parts: string[] = []
    let lastIndex = 0
    let match
    
    // 重置正则表达式
    idCardRegex.lastIndex = 0
    
    while ((match = idCardRegex.exec(textStr)) !== null) {
      // 添加匹配前的文本
      if (match.index > lastIndex) {
        parts.push(textStr.substring(lastIndex, match.index))
      }
      // 添加身份证号码（作为特殊标记）
      parts.push(`__ID_CARD__${match[0]}__`)
      lastIndex = match.index + match[0].length
    }
    
    // 添加剩余文本
    if (lastIndex < textStr.length) {
      parts.push(textStr.substring(lastIndex))
    }
    
    // 使用Vue的h函数创建VNode
    return h('span', {}, parts.map(part => {
      if (part.startsWith('__ID_CARD__') && part.endsWith('__')) {
        const cardNumber = part.replace('__ID_CARD__', '').replace('__', '')
        return h('span', {
          class: 'id-card-number',
          'data-id-card': cardNumber,
          draggable: true,
          onDragstart: (e: DragEvent) => handleIdCardDragStart(e),
          onMousedown: (e: MouseEvent) => {
            e.stopPropagation()
            handleIdCardClick(e)
          },
          onDblclick: (e: MouseEvent) => {
            e.stopPropagation()
            handleIdCardDoubleClick(e)
          }
        }, [HandIcon(), cardNumber])
      }
      return part
    }))
  }
  
  return textStr
}

// 处理身份证号码拖拽开始
const handleIdCardDragStart = (event: DragEvent) => {
  event.stopPropagation() // 阻止事件冒泡，避免触发节点拖拽
  const target = event.target as HTMLElement
  // 查找最近的.id-card-number元素
  const idCardElement = target.closest('.id-card-number') as HTMLElement
  const idCard = idCardElement?.getAttribute('data-id-card')
  if (idCard && event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'copy'
    event.dataTransfer.setData('text/plain', idCard)
    event.dataTransfer.setData('application/id-card', idCard)
    event.dataTransfer.setData('source-node-id', props.nodeId)
    // 注意：不在这里创建节点，只在 drop 事件中创建，避免重复创建
  }
}

// 处理身份证号码双击创建节点
const handleIdCardDoubleClick = (event: MouseEvent) => {
  event.stopPropagation()
  event.preventDefault()
  const target = event.target as HTMLElement
  const idCardElement = target.closest('.id-card-number') as HTMLElement
  if (idCardElement) {
    const idCard = idCardElement.getAttribute('data-id-card')
    if (idCard) {
      console.log('双击身份证号码，创建节点:', idCard)
      emit('createPersonNode', idCard)
    }
  }
}

// 处理身份证号码点击（仅用于阻止事件冒泡，不创建节点）
const handleIdCardClick = (event: MouseEvent) => {
  event.stopPropagation()
  // 不在这里创建节点，只在 drop 事件中创建，避免重复创建
}

// 转换列配置为 ant-design-vue 格式
const tableColumns = computed(() => {
  return props.columns.map(col => {
    const column: any = {
      title: col.label,
      dataIndex: col.prop,
      key: col.prop,
      width: col.width,
      ellipsis: {
        showTitle: true // 显示完整内容的tooltip
      }
    }
    
    // 如果列数据可能包含身份证号码，自定义渲染
    column.customRender = ({ text, record }: any) => {
      const cellContent = renderCellWithIdCard(text, record, col)
      // 如果返回的是字符串，直接返回（ant-design-vue会自动处理ellipsis和tooltip）
      if (typeof cellContent === 'string') {
        return cellContent
      }
      // 如果返回的是VNode，需要确保外层容器支持ellipsis
      return cellContent
    }
    
    return column
  })
})


// 计算当前页数据
const tableData = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return filteredData.value.slice(start, end).map((item, index) => ({
    ...item,
    key: start + index // 添加key用于表格渲染
  }))
})

// 处理搜索
const handleSearch = (values: Record<string, any>) => {
  searchValues.value = values
  currentPage.value = 1
}

// 处理重置
const handleReset = () => {
  searchValues.value = {}
  currentPage.value = 1
}

const handlePageChange = (page: number) => {
  currentPage.value = page
}

const handleSizeChange = (current: number, size: number) => {
  pageSize.value = size
  currentPage.value = 1
}

const handleDelete = () => {
  if (props.nodeId) {
    emit('delete', props.nodeId)
  }
}

// 调整大小相关
const isResizing = ref(false)
const startX = ref(0)
const startY = ref(0)
const startWidth = ref(0)
const startHeight = ref(0)

const handleResizeStart = (e: MouseEvent) => {
  e.preventDefault()
  e.stopPropagation()
  isResizing.value = true
  startX.value = e.clientX
  startY.value = e.clientY
  startWidth.value = props.width || 500
  startHeight.value = props.height || 300
  
  document.addEventListener('mousemove', handleResizeMove)
  document.addEventListener('mouseup', handleResizeEnd)
  document.body.style.userSelect = 'none'
  document.body.style.cursor = 'nwse-resize'
}

const handleResizeMove = (e: MouseEvent) => {
  if (!isResizing.value) return
  const deltaX = e.clientX - startX.value
  const deltaY = e.clientY - startY.value
  const newWidth = Math.max(400, startWidth.value + deltaX)
  const newHeight = Math.max(250, startHeight.value + deltaY)
  emit('resize', props.nodeId, newWidth, newHeight)
}

const handleResizeEnd = () => {
  isResizing.value = false
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
  document.body.style.userSelect = ''
  document.body.style.cursor = ''
}

onUnmounted(() => {
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
})

// 处理节点鼠标按下事件 - 确保拖拽功能正常
const handleNodeMouseDown = (e: MouseEvent) => {
  // 如果点击的是按钮、调整大小拖拽点或Handle，不阻止事件
  const target = e.target as HTMLElement
  if (
    target.closest('.delete-btn') ||
    target.closest('.resize-handle') ||
    target.closest('.vue-flow__handle') ||
    target.closest('.ant-table') ||
    target.closest('.ant-pagination') ||
    target.closest('.id-card-number')
  ) {
    return
  }
  // 其他区域允许拖拽，不阻止默认行为
}

// 处理节点双击事件
const handleNodeDoubleClick = (e: MouseEvent) => {
  // 如果点击的是按钮、调整大小拖拽点或Handle，不处理双击
  const target = e.target as HTMLElement
  if (
    target.closest('.delete-btn') ||
    target.closest('.resize-handle') ||
    target.closest('.vue-flow__handle') ||
    target.closest('.ant-table') ||
    target.closest('.ant-pagination') ||
    target.closest('.id-card-number')
  ) {
    return
  }
  console.log('Node double clicked in component:', props.nodeId)
}
</script>

<style scoped lang="less">
.table-node {
  padding: 10px 8px;
  border-radius: 8px;
  min-width: 400px;
  width: 500px;
  min-height: 250px;
  height: 300px;
  background: #ffffff;
  border: 2px solid #722ed1;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
  cursor: grab; // 与其他组件保持一致
  position: relative;
  
  &:active {
    cursor: grabbing; // 拖拽时显示grabbing
  }
  overflow: visible; // 改为 visible，确保 Handle 和调整大小点不被裁剪
  box-sizing: border-box;
  display: flex;
  flex-direction: column;

  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }

  // 选中状态样式
  &.node-selected {
    border-color: #1890ff;
    border-width: 3px;
    box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.2), 0 4px 16px rgba(24, 144, 255, 0.3);
  }

  :deep(.vue-flow__handle) {
    width: 4px !important;
    height: 4px !important;
    background: #722ed1 !important;
    border: 2px solid #ffffff !important;
    border-radius: 50% !important;
    z-index: 1000 !important;
    opacity: 0.9;
    cursor: crosshair !important;
    pointer-events: auto !important;
    padding: 4px !important;
    margin: -4px !important;
    box-sizing: content-box !important;
    position: absolute !important;

    &:hover {
      opacity: 1 !important;
      background: #9254de !important;
      box-shadow: 0 0 8px rgba(114, 46, 209, 0.6) !important;
      z-index: 1001 !important;
    }
  }

  .delete-btn {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 4px;
    cursor: pointer;
    z-index: 1002;
    opacity: 1; // 一直显示，与其他组件保持一致
    transition: background-color 0.2s ease;
    color: #8c8c8c;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

    &:hover {
      background: #ff4d4f;
      color: #ffffff;
    }
  }

  .resize-handle {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 12px;
    height: 12px;
    background: #722ed1;
    border: 2px solid #ffffff;
    border-radius: 50%;
    cursor: nwse-resize;
    z-index: 1002;
    opacity: 0;
    transition: opacity 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
    transform: translate(50%, 50%);

    &:hover {
      opacity: 1 !important;
      background: #9254de;
      box-shadow: 0 0 8px rgba(114, 46, 209, 0.6);
    }

    &:active {
      background: #531dab;
    }
  }

  &:hover .resize-handle {
    opacity: 0.8;
  }

  .progress-container {
    width: 100%;
    height: 100%;
    padding: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 400px;
    min-height: 250px;
    box-sizing: border-box;
  }

  .progress-bar-wrapper {
    width: 100%;
    height: 8px;
    background: #f0f0f0;
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 12px;
  }

  .progress-bar {
    height: 100%;
    background: linear-gradient(90deg, #722ed1 0%, #9254de 100%);
    border-radius: 4px;
    transition: width 0.1s linear;
  }

  .progress-text {
    font-size: 14px;
    font-weight: 600;
    color: #722ed1;
  }

  .table-content {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    overflow: hidden;
  }

  .empty-container {
    width: 100%;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    padding: 20px;
  }

  .table-title {
    font-size: 16px;
    font-weight: 600;
    color: #722ed1;
    text-align: center;
    padding: 8px 0;
    margin-bottom: 8px;
    flex-shrink: 0;
    border-bottom: 1px solid #e8e8e8;
  }

  // 搜索模块样式
  :deep(.dynamic-search) {
    flex-shrink: 0;
  }

  .pagination {
    margin-top: 8px;
    display: flex;
    justify-content: flex-end;
    flex-shrink: 0;
  }

  // 覆盖 ant-design-vue 表格样式以适应节点
  :deep(.ant-table) {
    font-size: 12px;
  }

  :deep(.ant-table-thead > tr > th) {
    padding: 8px;
    font-size: 12px;
  }

  :deep(.ant-table-tbody > tr > td) {
    padding: 8px;
    font-size: 12px;
  }
  
  // 确保单元格内容支持溢出隐藏和tooltip
  :deep(.ant-table-cell) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    
    // 确保单元格内的内容也支持溢出隐藏
    > * {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      max-width: 100%;
    }
  }
  
  // 确保身份证号码元素也支持溢出隐藏
  :deep(.ant-table-cell .id-card-number) {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
  }

  // 身份证号码样式
  :deep(.id-card-number) {
    color: #1890ff;
    cursor: grab;
    user-select: none;
    font-weight: 500;
    padding: 2px 4px;
    border-radius: 3px;
    transition: background-color 0.2s ease;

    &:hover {
      background-color: rgba(24, 144, 255, 0.1);
    }

    &:active {
      cursor: grabbing;
    }
  }
}
</style>

